/*
 *    Copyright 2019 CManLH
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.lifeonwalden.fa4py;

import com.lifeonwalden.fa4py.common.constant.UnicodeRange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Pattern;

/**
 * 解析字典
 */
public class Builder {
    private final static Logger logger = LoggerFactory.getLogger(Builder.class);

    private final String DEFAULT_DICTIONARY_FILE = "/fa4py.txt";
    private final String PROPERTY_FILE = "/fa4py.properties";
    private final Pattern pattern = Pattern.compile("^.:[a-z](,[a-z])*$");

    /**
     * 解析语境区分字典
     *
     * @return 字典项
     */
    public String[][] build() {
        InputStream propsInputStream = this.getClass().getResourceAsStream(PROPERTY_FILE);
        if (null == propsInputStream) {
            String errMsg = "Not find the property file fa4py.property at the root of classpath.";
            logger.debug(errMsg);

            throw new RuntimeException(errMsg);
        } else {
            try {
                Properties properties = new Properties();
                properties.load(propsInputStream);
                String[][] dicItems = new String[properties.size()][];
                for (Map.Entry<Object, Object> entry : properties.entrySet()) {
                    int ctxIndex = Integer.parseInt(String.valueOf(entry.getKey()));
                    if (ctxIndex >= properties.size()) {
                        String errMsg = "The context number should be start from zero and increased by one.";
                        logger.debug(errMsg);

                        throw new RuntimeException(errMsg);
                    }
                    dicItems[ctxIndex] = build(parse(String.valueOf(entry.getValue())));
                }

                return dicItems;
            } catch (IOException e) {
                logger.debug("Failed to load fa4py property file.", e);

                throw new RuntimeException(e);
            }
        }
    }

    private String[] build(InputStreamReader reader) throws IOException {
        String[] items = new String[UnicodeRange.MAX_CODE - UnicodeRange.MIN_CODE + 1];
        try (BufferedReader bufferedReader = new BufferedReader(reader)) {
            String _item = bufferedReader.readLine();
            while (null != _item) {
                if (!pattern.matcher(_item).matches()) {
                    String errMsg = "Not a valid dictionary item : ".concat(_item);
                    logger.debug(errMsg);

                    throw new RuntimeException(errMsg);
                }

                String[] itemSnippet = _item.split(":");
                items[itemSnippet[0].trim().codePointAt(0) - UnicodeRange.MIN_CODE] = itemSnippet[1].trim();

                _item = bufferedReader.readLine();
            }

            return items;
        }
    }

    private InputStreamReader parse(String pathInfo) throws FileNotFoundException {
        if (null == pathInfo || pathInfo.isEmpty()) {
            String errMsg = "Invalid path.";
            logger.debug(errMsg);

            throw new RuntimeException(errMsg);
        }

        if (pathInfo.toLowerCase().startsWith("classpath")) {
            return new InputStreamReader(this.getClass().getResourceAsStream(pathInfo.substring(pathInfo.indexOf(":") + 1)));
        } else {
            return new InputStreamReader(new FileInputStream(pathInfo));
        }
    }
}
